package com.uchengwang.functions.http.core;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import com.alibaba.fastjson.JSONObject;
import com.uchengwang.functions.http.config.BaseConfig;
import com.uchengwang.functions.http.config.RequestConfig;
import com.uchengwang.functions.http.listener.HttpCallBack;
import com.uchengwang.functions.http.listener.IBaseRequest;
import com.uchengwang.functions.http.listener.IHttpManager;
import com.uchengwang.ui.UChengApplication;
import com.uchengwang.ui.cm_ui.login.ui.LoginActivity;
import com.uchengwang.ui.utils.DialogUtils;
import com.uchengwang.ui.utils.JsonUtils;
import com.uchengwang.ui.utils.SPUtils;
import com.uchengwang.ui.utils.UCommonUtil;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * okhttp处理请求的底层封装类
 * Created by U城网 on 2017/3/2.
 */

public final class HttpCore {

    private OkHttpClient okhttp ;
    private Activity activity;
    private boolean isAnd = false;//当为get请求且只有一个字段时, 按照 ?key=value拼接

   public HttpCore(Activity activity){
       this.activity = activity;
        okhttp = UChengApplication.getHttpClient();
    }

    public void setAnd(boolean isAnd){
        this.isAnd = isAnd;
    }


    /**
     * 异步请求方法
     *
     * @param requestMethod 请求方法
     * @param isForm 是否以表单格式提交数据
     * @param url           请求URL
     * @param request       请求参数
     * @param callBack      请求回调
     * @return Call
     * @throws IOException
     */
    public Call query(IHttpManager.RequestMethod requestMethod, boolean isForm, String url, final IBaseRequest request, final HttpCallBack callBack) {
        if (requestMethod == null){
            return null;
        }

        Call call = buildCall(true, requestMethod,isForm, url, request);
        Log.d("jjf", "url=="+url);
        execute(true, call, callBack);
        return call;
    }

    /**
     * 异步请求方法
     *
     * @param requestMethod 请求方法
     * @param url           请求URL
     * @param request       请求参数拼接好的参数地址
     * @param callBack      请求回调
     * @return Call
     * @throws IOException
     */
    public Call queryString(IHttpManager.RequestMethod requestMethod, String url, final String request, final HttpCallBack callBack) {
        if (requestMethod == null){
            return null;
        }

        Call call = buildCallString(requestMethod, url, request);
        Log.d("jjf", "url=="+url);
        execute(true, call, callBack);
        return call;
    }

    /**
     * 调用别的网站的接口, 请求数据
     * */
    public Call queryOther(IHttpManager.RequestMethod requestMethod, boolean isForm, String url, final IBaseRequest request, final HttpCallBack callBack){
        if (requestMethod == null){
            return null;
        }

        Call call = buildCall(false, requestMethod,isForm, url, request);
        Log.d("jjf", "url=="+url);
        execute(false, call, callBack);
        return call;
    }

    /**
     * 异步开始请求网络
     * @param isUCity true 是U城的请求 false是别的网站的请求的数据
     * */
    private void execute(final boolean isUCity, Call call, final HttpCallBack callBack){
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                //这个onFailure执行的线程并不是UI线程
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        callBack.onError(-100, e.getMessage());
                    }
                });
            }

            @Override
            public void onResponse(final Call call, final Response response) {
                //这个onResponse执行的线程并不是UI线程
                final int code = response.code();
                String body = "";
                try {
                    //拿取数据 不能再主线程拿取，不然会报错
                    body = response.body().string();
                    Log.d("jjf","http_code="+code+"==body="+body);

                    if (isUCity){
                        //是来自U城的网络请求
                        if (code == 200 && !TextUtils.isEmpty(body)){
//                        JSONObject jsonObject = new JSONObject(body);
                            JSONObject object = JsonUtils.getManager().getJSONObject(body);
                            final int status = object.getIntValue("status");
                            final String msg = object.getString("msg");
                            final String data = object.getString("data");

//                        final String finalBody = body;
                            activity.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    //http的code
                                    callBack.onResp(status, msg, data);
                                }
                            });
                        }else {
                            activity.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    //http的code
                                    switch (code){
                                        case 403:
                                            //重新登陆
//                                        callBack.onError(code, "禁止访问");
                                            callBack.onError(code, "验证过期, 重新登录");
                                            DialogUtils.getUtils().showDialogSingle(activity, false, "", "验证过期, 请您重新登录", "确定", new View.OnClickListener() {
                                                @Override
                                                public void onClick(View view) {
                                                    DialogUtils.getUtils().cancel();

                                                    SPUtils.getPreferences(activity).setToken("");
                                                    SPUtils.getPreferences(activity).setRyToken("");
                                                    UChengApplication.TOKEN = "";
                                                    activity.startActivity(new Intent(activity, LoginActivity.class));
                                                }
                                            });

                                            break;
                                        case 401:
                                            callBack.onError(code, "未授权");
                                            break;
                                        case 500:
                                            callBack.onError(code, "服务器错误");
                                            break;
                                        case 404:
                                            callBack.onError(code, "暂无数据");
                                            break;
                                        default:
                                            callBack.onError(code, "获取失败");
                                            break;
                                    }
                                }
                            });
                        }
                    }else {
                        //来自别的网站的数据请求 直接将别的网站返回的数据 转为jsonString返回
                        final String finalBody = body;
                        activity.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //http的code
                                callBack.onResp(0, "", finalBody);
                            }
                        });
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            callBack.onError(-11, "失败");
                        }
                    });
                }
            }
        });
    }

    /**
     * 同步请求方法
     * @param requestMethod 请求方法
     * @param isForm 是否以表单格式提交数据
     * @param url           请求URL
     * @param request       请求参数
     * @return
     * @throws IOException
     */
    public Response synQuery(IHttpManager.RequestMethod requestMethod, boolean isForm, String url, IBaseRequest request) throws IOException {
        if (requestMethod == null){
            return null;
        }
        //需要自己开启个子线程请求
        Call call = buildCall(true, requestMethod,isForm, url, request);
        return call.execute();
    }


    /**
     * 表单格式提交
     * @param url     请求的ActionURL
     * @param request 请求参数
     * @return
     */
    private Request postBuilderForm(IHttpManager.RequestMethod method, String url, IBaseRequest request) {
        if (url == null) {
            url = "";
        }
        RequestBody body = null;
        String requestData = "";
        //表单格式提交数据
        FormBody.Builder builder = new FormBody.Builder();
        if (request != null) {
            HashMap<String, Object> data = request.getData();
            requestData = data.toString();
            if (data != null) {
                Iterator iter = data.keySet().iterator();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    String val = (String) data.get(key);
                    //添加表单键值
                    builder.add(key, val);
                }
            }
        }
        //生成表单实体对象
        body = builder.build();
        //补全请求地址
        String requestUrl = String.format("%s%s", BaseConfig.BaseURL, url);

        Log.i("ucw", "requestMethod -> , " + "URL -> " + requestUrl + " , requestData -> " + requestData);

        //创建一个请求
        Request req = null;
        switch (method){
            case PUT:
                req = addHeaders(IHttpManager.RequestMethod.PUT).url(requestUrl).put(body).build();
                break;
            case POST:
                req = addHeaders(IHttpManager.RequestMethod.POST).url(requestUrl).post(body).build();
                break;
        }

        return req;
    }


    /**
     * 以Application/Json提交
     * @param isUcity true是U城的请求 false不是U城的请求
     * @param url     请求的ActionURL
     * @param request 请求参数
     * @return
     */
    private Request postBuilderJson(boolean isUcity, IHttpManager.RequestMethod method, String url, IBaseRequest request) {
        if (url == null) {
            url = "";
        }
        String requestUrl = "", requestString = "";
        RequestBody body = null;

        if (request !=null){
            //json格式提交数据
            HashMap<String, Object> data = request.getData();

            requestString = JsonUtils.getManager().MapToString(data);
            Log.d("jjf", "发送请求的参数="+requestString);
        }
        body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestString);
        //补全请求地址
        if (isUcity){
            requestUrl = String.format("%s%s", BaseConfig.BaseURL, url);
        }else {
            requestUrl = String.format("%s", url);
        }

        Log.i("ucw", "requestMethod -> , " + "URL -> " + requestUrl + " , requestString -> " + requestString);

        //创建一个请求
        Request req = null;
        switch (method){
            case PUT:
                req = addHeaders(IHttpManager.RequestMethod.PUT).url(requestUrl).put(body).build();
                break;
            case POST:
                req = addHeaders(IHttpManager.RequestMethod.POST).url(requestUrl).post(body).build();
                break;
        }
        return req;
    }


    /**
     * 构建GET请求Request
     *@param isUCity true 是U城的请求 false不是
     * @param url     请求的ActionURL
     * @param request 请求参数
     * @return
     */
    private Request getBuilder(boolean isUCity, IHttpManager.RequestMethod method, String url, IBaseRequest request) {

        if (url == null) {
            url = "";
        }

        StringBuilder tempParams = new StringBuilder();
        String requestData = "";
        try {
            if (request != null) {
                HashMap<String, Object> data = request.getData();
                requestData = data.toString();
                if (data != null) {
                    int size = data.size();

                    Iterator iter = data.keySet().iterator();
                    if (size == 1){//就一个字段
                        String key = (String) iter.next();
                        String val = (String) data.get(key);

                        if (isAnd){
                            tempParams.append("?");
                            tempParams.append(String.format("%s=%s", key, URLEncoder.encode(URLEncoder.encode(val, "utf-8"), "utf-8")));
                        }else {
                            tempParams.append("/");
                            tempParams.append(String.format("%s", URLEncoder.encode(URLEncoder.encode(val, "utf-8"), "utf-8")));
                        }


                    }else {//多个字段
                        boolean isFirst = true;
                        while (iter.hasNext()) {
                            String key = (String) iter.next();
                            String val = (String) data.get(key);

                            if (isFirst){
                                tempParams.append("?");
                                isFirst = false;
                            }else {
                                tempParams.append("&");
                            }
                            if (TextUtils.isEmpty(val)){
                                continue;
                            }
//                            URLDecoder.decode(URLEncoder.encode(val, "utf-8"), "utf-8")
                            tempParams.append(String.format("%s=%s", key, URLEncoder.encode(URLEncoder.encode(val, "utf-8"), "utf-8")));

                        }
                    }
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String requestUrl = "";
        if (isUCity){
            requestUrl = String.format("%s%s%s", BaseConfig.BaseURL, url, tempParams.toString());
        }else {
            requestUrl = String.format("%s%s", url, tempParams.toString());
        }
        Log.i("ucw", "requestMethod -> , " + "URL -> " + requestUrl + " , requestData -> " + requestData);

        Request req = null;
        switch (method){
            case GET:
                req = addHeaders(IHttpManager.RequestMethod.GET).get().url(requestUrl).build();
                break;
            case DELETE:
                req = addHeaders(IHttpManager.RequestMethod.DELETE).delete().url(requestUrl).build();
                break;

        }
        return req;
    }

    /**
     * 构建GET请求Request
     *
     * @param url     请求的ActionURL
     * @param request 请求参数 拼接好的地址
     * @return
     */
    private Request getBuilderString(IHttpManager.RequestMethod method, String url, String request) {
        if (TextUtils.isEmpty(url) || TextUtils.isEmpty(request)) {
            return null;
        }

        String requestUrl = String.format("%s%s%s", BaseConfig.BaseURL, url, request);
        Log.i("ucw", "requestMethod -> , " + "URL -> " + requestUrl + " , requestData -> " + request);

        Request req = null;
        switch (method){
            case GET:
                req = addHeaders(IHttpManager.RequestMethod.GET).get().url(requestUrl).build();
                break;
            case DELETE:
                req = addHeaders(IHttpManager.RequestMethod.DELETE).delete().url(requestUrl).build();
                break;
        }
        return req;
    }

    /**
     * 根据请求方法、请求URL、请求参数构建Call对象
     * @param isCity true 是U城的请求  false不是U城的请求
     * @param requestMethod 请求方法
     * @param isForm 是否以表单格式提交数据
     * @param url           请求URL
     * @param request       请求参数
     * @return Call
     */
    private Call buildCall(boolean isCity, IHttpManager.RequestMethod requestMethod,boolean isForm, String url, IBaseRequest request) {
        Request builder = null;
        //put和post请求类似    delete和get请求类似
        switch (requestMethod) {
            case GET:
            case DELETE:
                builder = getBuilder(isCity, requestMethod, url, request);
                break;

            case POST:
            case PUT:
                if (isForm){
                    builder = postBuilderForm(requestMethod, url, request);
                }else {
                    builder = postBuilderJson(isCity, requestMethod,url, request);
                }
                break;
        }

        Call call = okhttp.newCall(builder);
        return call;
    }

    private Call buildCallString(IHttpManager.RequestMethod requestMethod, String url, String request){
        Request builder = null;
        //put和post请求类似    delete和get请求类似
        switch (requestMethod) {
            case GET:
            case DELETE:
                builder = getBuilderString(requestMethod, url, request);
                break;
        }

        Call call = okhttp.newCall(builder);
        return call;
    }


    /**
     * 统一为请求添加头信息
     * @return
     */
    private Request.Builder addHeaders(IHttpManager.RequestMethod method) {

        Log.d("ucw", "请求方法="+method);
        Request.Builder builder = new Request.Builder()
                .addHeader("platform", "2")
                .addHeader("phoneModel", Build.MODEL)
                .addHeader(BaseConfig.DEVICE_ID, UCommonUtil.getUtil().getDeviceId(activity))
                .addHeader("systemVersion", RequestConfig.SYSTEM_VERSION)
                .addHeader("appVersion", "3.2.0")
                .addHeader("time", String.valueOf(System.currentTimeMillis()))
                .addHeader("deviceType", "2");//Byte  1-ios ,2-android
        if (!TextUtils.isEmpty(UChengApplication.TOKEN)){
            builder.addHeader("Authorization", UChengApplication.TOKEN);
        }
//        builder.addHeader("User-Agent", "ucheng");
        Log.d("ucw", "添加Token="+UChengApplication.TOKEN);
        return builder;
    }

}
